﻿//矩阵和行列式运算
//本文件由贺镇涛(2021300004071) 高肇鸿(学号) 共同负责
#pragma once
#include<string>
#include<iostream>
using namespace std;
//贺镇涛：
// 矩阵和行列式（除求逆）
int matanddet(string s);
class Mat //为了编写方便，编写的时候从1开始，写完后出于节约资源的考虑，把所有的数字减去一，字母改为从0开始
{
private:
	int m = 0, n = 0;
	double laplace_expansion(double matrix[26][26], int i, int j, int order);//拉普拉斯展开
	double order_judge(double mat[26][26], int order);

public:
	//求逆所需部分，参考csdn@jdh99
	int m1 = m;
	int n1 = n;
	//定义指针arr，用于调用数组数据
	double* arr = 0;
	//矩阵初始化
	void init_mat()
	{
		arr = new double[m * n];
	}
	//矩阵释放
	void free_mat()
	{
		delete[]arr;
	}
	//矩阵数据读取【坐标为（i，j）的数据】
	//失败返回值-3
	double read_mat(int i, int j)
	{
		if (i >= m || j >= n)
		{
			return -3;
		}
		return *(arr + i * n + j);
	}
	//矩阵数据写入【坐标为（i，j）的数据】
	//成功返回值1，失败返回-1
	int write_mat(int i, int j, double val)
	{
		if (i >= m || j >= n)
		{
			return -1;
		}
		*(arr + i * n + j) = val;
		return 1;
	}
	//打印矩阵
	void printf_mat(Mat* A)
	{
		int i = 0;
		int j = 0;
		int m = 0;
		int n = 0;
		m = A->m, n = A->n;
		for (i = 0; i < m; i++)
		{
			for (j = 0; j < n; j++)
			{
				printf("%f ", A->read_mat(i, j));
			}
			printf("\n");
		}
	}
	//以上求逆所需，或可扩展至整个矩阵模块的运算结构

	double a[26][26] = {};
	Mat() {}						//默认构造函数
	Mat(int tempm, int tempn)
	{
		m = tempm; n = tempn;
		for (int i = 1; i <= m; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				cin >> a[i][j];
			}
		}
		cout << endl;
	}
	void print()
	{
		for (int i = 1; i <= m; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				cout << a[i][j] << " ";
			}
			cout << endl;
		}
	}
	double det_cal();
	void transpo();
};

//高肇鸿：
//修正求逆错误，结果矩阵类
class Matfix
{
private:
	int m = 0, n = 0;

public:
	//求逆所需部分，参考csdn@jdh99
	int m1 = m;
	int n1 = n;
	//定义指针arr，用于调用数组数据
	double* arr = 0;
	//矩阵初始化
	void init_mat()
	{
		arr = new double[m * n];
	}
	//矩阵释放
	void free_mat()
	{
		delete[]arr;
	}
	//矩阵数据读取【坐标为（i，j）的数据】
	//失败返回值-3
	double read_mat(int i, int j)
	{
		if (i >= m || j >= n)
		{
			return -3;
		}
		return *(arr + i * n + j);
	}
	//矩阵数据写入【坐标为（i，j）的数据】
	//成功返回值1，失败返回-1
	int write_mat(int i, int j, double val)
	{
		if (i >= m || j >= n)
		{
			return -1;
		}
		*(arr + i * n + j) = val;
		return 1;
	}
	//打印矩阵
	static void printf_mat(Matfix* A)
	{
		int i = 0;
		int j = 0;
		int m = 0;
		int n = 0;
		m = A->m1, n = A->n1;
		for (i = 0; i < m; i++)
		{
			for (j = 0; j < n; j++)
			{
				printf("%f ", A->read_mat(i, j));
			}
			printf("\n");
		}
	}
	Matfix(int tempm, int tempn) {}
};

//定义矩阵计算方法类
class Mat_cal
{
public:
	static void add(double adda[26][26], double addb[26][26], int ma, int mb, int na, int nb);
	static void subtract(double suba[26][26], double subb[26][26], int ma, int mb, int na, int nb);
	static void multiply(double mula[26][26], double mulb[26][26], int ma, int na, int mb, int nb);
	//对矩阵求逆
	static int inverse(Mat* A, Matfix* B)
	{
		int i = 0;
		int j = 0;
		int k = 0;
		Matfix inv_a(A->m1, 2 * A->m1);
		double temp = 0;
		double b = 0;
		//增广矩阵M=A|B初始化
		inv_a.init_mat();
		for (i = 0; i < inv_a.m1; i++)
		{
			for (j = 0; j < inv_a.n1; j++)
			{
				if (j <= A->n1 - 1)
				{
					inv_a.write_mat(i, j, A->read_mat(i, j));
				}
				else
				{
					if (i == j - A->n1)
					{
						inv_a.write_mat(i, j, 1);
					}
					else
					{
						inv_a.write_mat(i, j, 0);
					}
				}
			}
		}
		//高斯消元法
		//将矩阵变换为下三角型
		for (k = 0; k < inv_a.m1 - 1; k++)
		{
			//如果坐标为k，k值为0，则行变换
			if (inv_a.read_mat(k, k) == 0)
			{
				for (i = k + 1; i < inv_a.m1; i++)
				{
					if (inv_a.read_mat(i, k) != 0)
					{
						break;
					}
				}
				if (i >= inv_a.m1)
				{
					return -1;
				}
				else
				{
					//交换行
					for (j = 0; j < inv_a.n1; j++)
					{
						temp = inv_a.read_mat(k, j);
						inv_a.write_mat(k, j, inv_a.read_mat(k + 1, j));
						inv_a.write_mat(k + 1, j, temp);
					}
				}
			}
			//消元
			for (i = k + 1; i < inv_a.m1; i++)
			{
				//获得倍数
				b = inv_a.read_mat(i, k) / inv_a.read_mat(k, k);
				//行变换
				for (j = 0; j < inv_a.n1; j++)
				{
					temp = inv_a.read_mat(i, j) - b * inv_a.read_mat(k, j);
					inv_a.write_mat(i, j, temp);
				}
			}
		}
		//变换上三角
		for (k = inv_a.m1 - 1; k > 0; k--)
		{
			//如果坐标为k，k值为0，则行变换
			if (inv_a.read_mat(k, k) == 0)
			{
				for (i = k + 1; i < inv_a.m1; i++)
				{
					if (inv_a.read_mat(i, k) != 0)
					{
						break;
					}
				}
				if (i >= inv_a.m1)
				{
					return -1;
				}
				else
				{
					//交换行
					for (j = 0; j < inv_a.n1; j++)
					{
						temp = inv_a.read_mat(k, j);
						inv_a.write_mat(k, j, inv_a.read_mat(k + 1, j));
						inv_a.write_mat(k + 1, j, temp);
					}
				}
			}
			//消元
			for (i = k - 1; i >= 0; i--)
			{
				//获得倍数
				b = inv_a.read_mat(i, k) / inv_a.read_mat(k, k);
				//行变换
				for (j = 0; j < inv_a.n1; j++)
				{
					temp = inv_a.read_mat(i, j) - b * inv_a.read_mat(k, j);
					inv_a.write_mat(i, j, temp);
				}
			}
		}
		//将左边方阵化为单位矩阵
		for (i = 0; i < inv_a.m1; i++)
		{
			if (inv_a.read_mat(i, i) != 1)
			{
				//获得倍数
				b = 1 / inv_a.read_mat(i, i);
				//行变换
				for (j = 0; j < inv_a.n1; j++)
				{
					temp = inv_a.read_mat(i, j) * b;
					inv_a.write_mat(i, j, temp);
				}
			}
		}
		//求得逆矩阵
		for (i = 0; i < B->m1; i++)
		{
			for (j = 0; j < B->m1; j++)
			{
				B->write_mat(i, j, inv_a.read_mat(i, j + inv_a.m1));
			}
		}
		//释放增广矩阵
		inv_a.free_mat();
		return 1;
	}
};
